#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#include "log.hpp"
#define BUF_SIZE 1024
class Udpserver
{
public:
    Udpserver(uint16_t port, std::string ip = "")
        : port_(port), ip_(ip), sockfd_(-1)
    {
        sockfd_ = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd_ < 0)
        {
            log(FATAL, "create server socket err");
            exit(-1);
        }
        std::cout<<port_<<std::endl;
        struct sockaddr_in local;
        local.sin_addr.s_addr = ip_.empty() ? htonl(INADDR_ANY) : inet_addr(ip_.c_str());
        local.sin_family = AF_INET;
        local.sin_port =htons(port_);
        if (bind(sockfd_, (const sockaddr *)&local, sizeof(local)) < 0)
        {
            log(FATAL, "server bind socket err");
            exit(-1);
        }
        log(DEBUG, "server bind success");
    }
    void loop()
    {
        char buffer[BUF_SIZE];
        while (true)
        {
            // 输出型参数
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            ssize_t s = recvfrom(sockfd_, buffer, sizeof(buffer), 0, (struct sockaddr *)&peer, &len);
            if (s > 0)
            {
                buffer[s] = '\0';
            }
            else
            {
                log(WARNING, "recvfrom fail");
                continue;
            }
            log(INFO, "[%s:%d]# %s", inet_ntoa(peer.sin_addr), ntohs(peer.sin_port), buffer);
        }
    }

private:
    std::string ip_;
    std::uint16_t port_;
    int sockfd_;
};

int main(int argc, char *argv[])
{
    if (argc != 2 && argc != 3)
    {
        log(FATAL, "usage:[%s port [ip]]", argv[0]);
    }
    else
    {
        // ./server port
        if (argc == 2)
        {
            std::cout<<atoi(argv[1])<<std::endl;
            Udpserver server(atoi(argv[1]));
            server.loop();
        }
        // ./server port ip
        else
        {
            Udpserver server(atoi(argv[1]), argv[2]);
            server.loop();
        }
    }
}
